﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Reflection;
using System.Globalization;

namespace devtm.Configuration.Models
{


    public enum ReturnIsValid
    {
        Unassigned,
        Ok,
        Information,
        Warning,
        Error

    }

    [AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = true)]
    public class PropertyItemAttribute : ConfigurationValidatorAttribute
    {

        private string IsValid;


        public PropertyItemAttribute(string label, string typeValue, Type type, string methodNameCanAssign, string methodIsValid)
        {

            this.Type = type;
            this.MethodNameCanAssign = methodNameCanAssign;
            this.IsValid = methodIsValid;
            this.Name = label;

            CanAssignMethodInfo = GetMethod(MethodNameCanAssign, _types, typeof(bool));
          
            MethodIsValid = GetMethod(methodIsValid, _types, typeof(ReturnIsValid));

        }



        /// <summary>
        /// Nom de la fonction renvoyant vrai ou faux pour afficher l'action.
        /// </summary>
        public string MethodNameCanAssign { get; set; }

        /// <summary>
        /// type de la classe contenant l'action
        /// </summary>
        public Type Type { get; set; }

        /// <summary>
        /// Name of the property
        /// </summary>
        public string Name { get; set; }
        public string DisplayName { get; set; }
        public MethodInfo CanAssignMethodInfo { get; set; }
        public MethodInfo MethodIsValid { get; set; }

        private static Type[] _types = new Type[] { typeof(object), typeof(IElementSection) };
        private MethodInfo GetMethod(string methodName, Type[] possibleParametersTypes, Type typeReturn)
        {

            MethodInfo m;

            var lst = Type.GetMethods(BindingFlags.Static | BindingFlags.Public)
                .Where(i => (i.Name == methodName)
                    && (i.GetParameters().Length == 1)
                    && possibleParametersTypes.Contains(i.GetParameters().First().ParameterType)
                    && (typeReturn == null || i.ReturnType == typeReturn)
                    ).ToList();

            if (lst.Count > 1)
                throw new Exception(string.Format("More one method match for {0}.{1} with object or IElementSection argument.", Type, methodName));

            if (lst.Count == 0)
                throw new Exception(string.Format("no one method match for {0}.{1} with object or IElementSection argument.", Type, methodName));

            m = lst.First();

            return m;
        }
    }
}
